use std::sync::RwLock;
use crate::PAGE_SIZE;

pub const PAGE_COUNT: usize = 1000;
const MEMORY_SIZE: usize = PAGE_SIZE * PAGE_COUNT;

use crate::address::PhysAddr;

use lazy_static::*;

pub fn memory_write_bytes(addr: PhysAddr, buffer: &[u8]) -> usize {
    let offset: usize = addr.into();
    let end = std::cmp::min(offset + buffer.len(), MEMORY_SIZE);
    MEMORY.write().unwrap()[offset..end].copy_from_slice(buffer);
    end - offset
}

pub fn memory_read_bytes(addr: PhysAddr, buffer: &mut [u8]) -> usize {
    let offset: usize = addr.into();
    let end = std::cmp::min(offset + buffer.len(), MEMORY_SIZE);
    buffer.copy_from_slice(&MEMORY.read().unwrap()[offset..end]);
    end - offset
}

pub fn memory_get_ref<T>(addr: PhysAddr) -> &'static T {
    let offset: usize = addr.into();

    unsafe {
        let addr = MEMORY.read().unwrap().as_ptr().add(offset) as usize;
        & *(addr as *const T)   
    }
}

pub fn memory_get_mut<T>(addr: PhysAddr) -> &'static mut T {
    let offset: usize = addr.into();

    unsafe {
        let addr = MEMORY.read().unwrap().as_ptr().add(offset) as usize;
        &mut *(addr as *mut T)
    }
}

lazy_static! {
    static ref MEMORY: RwLock<Vec<u8>> = {
        RwLock::new(vec![0u8; MEMORY_SIZE])
    };
}